#include "vsf_hal.h"
#include "hme_gpio.h"

static void __longdelay()
{
    int i;
    for (i = 0; i < 10000000; i++) {
        __NOP();
    }
}

static void __gpio0_3_isr_handler(void *target_ptr, vsf_gpio_t *gpio_ptr,
                                  vsf_gpio_pin_mask_t pin_mask)
{
    if (pin_mask & GPIO_PIN3) {
        vsf_hw_gpio_toggle(&vsf_hw_gpio0, GPIO_PIN0);
    }
}

void vsf_gpio_interrupt_task()
{
    vsf_hw_gpio_config_pin(&vsf_hw_gpio0, GPIO_PIN0 | GPIO_PIN1, 0);
    vsf_hw_gpio_set_output(&vsf_hw_gpio0, GPIO_PIN0 | GPIO_PIN1);

    vsf_hw_gpio_config_pin(&vsf_hw_gpio0, GPIO_PIN3, VSF_GPIO_EXTI_ENABLED);
    vsf_hw_gpio_set_input(&vsf_hw_gpio0, GPIO_PIN3);

    vsf_gpio_pin_irq_cfg_t cfg = {
        .pin_mask = GPIO_PIN3,
        .mode     = VSF_GPIO_INT_MODE_RISING,
        .isr =
            {
                .handler_fn = __gpio0_3_isr_handler,
                .target_ptr = NULL,
            },
    };
    vsf_hw_gpio_exti_config(&vsf_hw_gpio0, &cfg);
    vsf_hw_gpio_exti_irq_enable(&vsf_hw_gpio0, GPIO_PIN3, VSF_ARCH_PRIO_1);

    while (1) {
        static uint32_t __cnt;
        if (__cnt++ > 1000000) {
            __cnt = 0;
            vsf_hw_gpio_toggle(&vsf_hw_gpio0, GPIO_PIN1);
        }
    }

    return;
}

void vsf_gpio_poll_task()
{
    vsf_hw_gpio_config_pin(&vsf_hw_gpio0, GPIO_PIN0 | GPIO_PIN1, 0);
    vsf_hw_gpio_set_output(&vsf_hw_gpio0, GPIO_PIN0 | GPIO_PIN1);

    vsf_hw_gpio_config_pin(&vsf_hw_gpio0, GPIO_PIN3, 0);
    vsf_hw_gpio_set_input(&vsf_hw_gpio0, GPIO_PIN3);

    while (1) {
        uint32_t pin_mask = vsf_hw_gpio_read(&vsf_hw_gpio0);
        if (pin_mask & GPIO_PIN3) {
            vsf_hw_gpio_set(&vsf_hw_gpio0, GPIO_PIN0);
        } else {
            vsf_hw_gpio_clear(&vsf_hw_gpio0, GPIO_PIN0);
        }

        static uint32_t __cnt;
        if (__cnt++ > 1000000) {
            __cnt = 0;
            vsf_hw_gpio_toggle(&vsf_hw_gpio0, GPIO_PIN1);
        }
    }

    return;
}

void vsf_gpio_toggle_task(void)
{
    vsf_hw_gpio_config_pin(&vsf_hw_gpio0, GPIO_PIN0 | GPIO_PIN1, 0);
    vsf_hw_gpio_set_output(&vsf_hw_gpio0, GPIO_PIN0 | GPIO_PIN1);

    while (1) {
        vsf_hw_gpio_set(&vsf_hw_gpio0, GPIO_PIN0 | GPIO_PIN1);
        __longdelay();
        vsf_hw_gpio_clear(&vsf_hw_gpio0, GPIO_PIN0 | GPIO_PIN1);
        __longdelay();

        vsf_hw_gpio_set(&vsf_hw_gpio0, GPIO_PIN0);
        __longdelay();
        vsf_hw_gpio_clear(&vsf_hw_gpio0, GPIO_PIN0);
        __longdelay();

        vsf_hw_gpio_set(&vsf_hw_gpio0, GPIO_PIN1);
        __longdelay();
        vsf_hw_gpio_clear(&vsf_hw_gpio0, GPIO_PIN1);
        __longdelay();
    }
}
